import wx
import wx.grid
import copy
import decimal
import time

from NumTool import myeval


class BaseTable(wx.grid.GridTableBase):

    
    def __init__(self, *args, **kwargs):
        super().__init__()
        # * 为整行/列
        # cols = [....]行标签label
        # rows = [....]列标签label
        # data = [[......], [......]]
        # func = {(row, col): func} 在row 行 col 列 写入 func 函数
        # disable = {(row, col): 'disable', ...} row,col 无法写入
        self.cols = kwargs.get('cols', [''])
        self.data = self.gendata(kwargs.get('data'))
        self.rows = self.genrows()
        
    def gendata(self, data):
        if data is None:
            data = []
            for i in range(30):
                datarow = ['' for i in self.cols]
                data.append(datarow)
        return data

    def genrows(self):
        return [str(i) for i in range(1, len(self.data) + 1)]

    def AppendRows(self, numRows=1):
        for num in range(0,numRows):
            newData = []
            for i in range(self.GetNumberCols()):
                newData.append('')
            self.data.append(newData)
            self.rows.append(str(int(self.rows[-1])+1))

        self.isModified = True
        gridView = self.GetView()
        gridView.BeginBatch()
        appendMsg = wx.grid.GridTableMessage(self,wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED,numRows)
        gridView.ProcessTableMessage(appendMsg)
        gridView.EndBatch()
        getValueMsg = wx.grid.GridTableMessage(self,wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        gridView.ProcessTableMessage(getValueMsg)
           
        return True

    def InsertRows(self, pos=0, numRows=1):
        for num in range(0,numRows):
            newData = []
            for i in range(self.GetNumberCols()):
                newData.append('')
            self.data.insert(pos,newData)
            self.rows.append(str(int(self.rows[-1])+1))
           
        gridView = self.GetView()
        gridView.BeginBatch()
        insertMsg = wx.grid.GridTableMessage(self,wx.grid.GRIDTABLE_NOTIFY_ROWS_INSERTED,pos,numRows)
        gridView.ProcessTableMessage(insertMsg)
        gridView.EndBatch()
        getValueMsg = wx.grid.GridTableMessage(self,wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        gridView.ProcessTableMessage(getValueMsg)       


        return True

    def DeleteRows(self,pos=0,numRows=1):
        if self.data is None or len(self.data) == 0:
            return False

        rows = [i for i in range(0,numRows)]
        rows.reverse()
        for rowNum in rows:
            self.data.remove(self.data[pos+rowNum])
            self.rows.pop()

        gridView = self.GetView()
        gridView.BeginBatch()
        deleteMsg = wx.grid.GridTableMessage(self,wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED,pos,numRows)
        gridView.ProcessTableMessage(deleteMsg)
        gridView.EndBatch()
        getValueMsg = wx.grid.GridTableMessage(self,wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        gridView.ProcessTableMessage(getValueMsg)


        
        return True


    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data[0])

    def IsEmptyCell(self, row, col):
        return False

    # @func_time
    def GetValue(self, row, col):
        try:
            value = self.data[row][col]
            return value
        except IndexError:
            return


    def SetValue(self, row, col, value):
        try:
            self.data[row][col] = str(value)
        except IndexError:
            try:
                self.data[row].append(str(value))
            except IndexError:
                pass

        
    def GetColLabelValue(self, col):
        return str(self.cols[col])
       
    def GetRowLabelValue(self, row):
        return self.rows[row]

    def GetData(self):
        return copy.deepcopy(self.data)
        
    def SetData(self, data):
        for row, rowv in enumerate(data):
            for col, value in enumerate(rowv):
                self.SetValue(row, col, str(value))
        # self.data = data
                
    @staticmethod
    def getsize(string):
        return dict()


if __name__ == "__main__":
    class TestFrame(wx.Frame):
        def __init__(self):
            super().__init__(None, title="Grid Table",
                            size=(1000,600))
            self.grid = wx.grid.Grid(self)
            # grid.SetLabelBackgroundColour('red')
            rows = []
            cols = []
            for i in range(10):
                rows.append(1)
                cols.append(2)
            data = []
            index = 0
            for row in rows:
                index += 1
                temp = []
                temp.append({'label':index})
                temp.append({'label':"haha"})
                # temp.append({'label':'=$(*,0)$*0.17+33'})
                # temp.append({'label':'&(*,0)&0.17&33&(*,1)'})
                temp.append({'label':1})
                temp.append({'label':1})
                temp.append({'label':1})
                temp.append({'label':1})
                temp.append({'label':1})
                temp.append({'label':1})
                data.append(temp)
            print(len(data[0]))
            print(len(data))
            disable = [['disable'], ['disable']]
            datalist = {'甲供':1, '乙供':2, '利旧':3}
            table = BaseTable(cols=cols)
            self.grid.SetTable(table, True)
            self.grid.AppendRows(0)
            table.SetData(data)
            
            btn = wx.Button(self, -1, 'button insert')
            btn2 = wx.Button(self, -1, 'button append')
            btn3 = wx.Button(self, -1, 'button del')
            self.Bind(wx.EVT_BUTTON, self.OnClick, btn)
            self.Bind(wx.EVT_BUTTON, self.OnClick2, btn2)
            self.Bind(wx.EVT_BUTTON, self.OnClick3, btn3)
            self.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.OnChanged)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.grid, 1, wx.EXPAND)
            sizer.Add(btn, 0, wx.EXPAND)
            sizer.Add(btn2, 0, wx.EXPAND)
            sizer.Add(btn3, 0, wx.EXPAND)
            self.SetSizer(sizer)

        def OnClick(self, event):
            self.grid.InsertRows()

        def OnClick2(self, event):
            self.grid.AppendRows()
            
        def OnClick3(self, event):
            self.grid.DeleteRows()

        def OnChanged(self, event):
            self.grid.ForceRefresh()
            


    app = wx.App()
    frame = TestFrame()
    frame.Show()
    app.MainLoop()
